<?php

namespace App\Http\Controllers\Mobile;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use App\Interfaces\OrderService;

use App\Services\AlipayCustoms\AlipayCustom;
use App\Services\Allinpay\Pay;
use App\Services\Allinpay\Responses\Pay as ResponsePay;
use App\Services\Allinpay\Utils\Form;
use App\Services\Wxpay\Models\UnifiedOrder;
use App\Services\Wxpay\Models\OrderQuery;
use App\Services\Wxpay\Wxpay;
use App\Services\Wxpay\Sdk\Notify;
use App\Services\Wxpay\Models\Results;

use App\Exceptions\Front\WxpayException;

use App\Models\Order;

use Auth,Container,Log;


class PayController extends Controller
{


    /**
     * 支付请求
     * @param  [type]       $order_id     [description]
     * @param  [type]       $type         [description]
     * @param  OrderService $orderService [description]
     * @return [type]                     [description]
     */
    public function request($order_id, $type, OrderService $orderService){

        $order = $orderService->getByOrderId($order_id);

        $subject = '';

        $goods_ids = '';

        foreach($order->orderGoods as $goods){

            $subject.='['.$goods->goods_name.']';

            $goods_ids .= '['.$goods->goods_id.']';
        }

       if ($order){

           switch($type){

               case 1:
                   //支付宝支付
                   return $this->aliPay($order->order_sn,$order->pay_price,$subject,$order->desc);
               break;

               case 2:
                   //通联支付
                   if($order->pay_status==0){

                       return $this->allinPay($order->order_sn, $order->pay_price, $order->create_time);
                   }//end if()
               break;

               case 3:
                   //微信支付
                   if($order->pay_status==0){

                       return $this->wxpay($order->order_sn, $order->pay_price, $subject, $goods_ids);
                   }//end if()
               break;
           }//end switch()


       }//end if()

    }


    /**
     * 支付成功
     * @param  [type]       $order_id     [description]
     * @param  OrderService $orderService [description]
     * @return [type]                     [description]
     */
    public function success($order_id,OrderService $orderService){

        $order = $orderService->getByOrderId($order_id);

        return view('mobile.pay.success',compact(['order','order_id']));
    }


    //支付宝

    private function aliPay($order_sn,$pay_price,$subject,$description){

        // 创建支付单。
        $alipay = app('alipay.wap');
        $alipay->setOutTradeNo($order_sn);
        $alipay->setTotalFee($pay_price);
        $alipay->setSubject($subject);
        $alipay->setBody('');

        return redirect($alipay->getPayLink());
    }

    //支付宝同步跳转页面
    public function aliPayRedirectBack(Request $request,OrderService $orderService){


//        // 验证请求。
//        if (! app('alipay.web')->verify()) {
//            Log::notice('Alipay return query data verification fail.', [
//                'data' => $request->getQueryString()
//            ]);
//            return '失败';
//
//        }

        // 判断通知类型。
        switch ($request->get('trade_status')) {
            case 'TRADE_SUCCESS':
            case 'TRADE_FINISHED':

                $order_sn = $request->get('out_trade_no');


                $order_id = $orderService->orderPayBack(
                    $order_sn,
                    'alipay',
                    $request->get('trade_no'),
                    $request->get('notify_time'),
                    json_encode($request->all())
                    );

                if ($order_id){
                    return redirect('/pay/success/'.$order_id);
                }
                // TODO: 支付成功，取得订单号进行其它相关操作。
                Log::debug('Alipay notify get data verification success.', [
                    'out_trade_no' => $request->get('out_trade_no'),
                    'trade_no' => $request->get('trade_no')
                ]);
                break;
        }

        return '成功';
    }

    //支付宝服务回调
    public function aliPayServerBack(Request $request,OrderService $orderService){

        Log::debug('Alipay wap notify get data verification success.', [
            'out_trade_no' => $request->get('out_trade_no'),
            'trade_no' => $request->get('trade_no')
        ]);

        // 验证请求。
        if (! app('alipay.web')->verify()) {

            Log::notice('Alipay notify post data verification fail.', ['data' => $request->getContent()]);

            return 'fail';
        }

        // 判断通知类型。
        switch ($request->get('trade_status')) {
            case 'TRADE_SUCCESS':
            case 'TRADE_FINISHED':


            $pay_sn = $request->get('out_trade_no');


            $order_pay_id = $orderService->orderPayBack(
                $pay_sn,
                'alipay',
                $request->get('trade_no'),
                $request->get('notify_time'),
                json_encode($request->all())
            );

            if ($order_pay_id){
                return 'success';
            }

            Log::debug('Alipay notify get data verification success.', [
                'out_trade_no' => $request->get('out_trade_no'),
                'trade_no' => $request->get('trade_no')
            ]);

            break;
        }

        return 'success';
        return 'fail';

    }

    /**
     * 生成微信支付二维码
     * @param  [type]       $order_id     [description]
     * @param  OrderService $orderService [description]
     * @return [type]                     [description]
     */
    public function wxpayScanUrl($order_id, OrderService $orderService){

        $order = $orderService->getByOrderId($order_id);

        $subject = '';

        $goods_ids = '';

        foreach($order->orderGoods as $goods){

            $subject.='['.$goods->goods_name.']';

            $goods_ids .= '['.$goods->goods_id.']';
        }

        $result = $this->wxpay($order->order_sn, $order->pay_price, $subject, $goods_ids);


        if (isset($result['code_url'])) {

            // $code_url = 'weixin://wxpay/bizpayurl?pr=R5zsq92';

            $code_url = $result['code_url'];

            $qr_code_url = $this->QRcode($code_url, $order->order_sn);

            $return['data'] = $qr_code_url;

            // echo '<img src="'.$qr_code_url.'" /><hr/>';
        }else{

            $return['status'] = 0;

            if (isset($result['return_code'])) {

                switch ($result['return_code']) {

                    case 'SUCCESS':

                        if (isset($result['result_code']) && $result['result_code'] == 'FAIL') {

                            $return['message'] = $result['err_code_des'];
                        }

                        break;

                    case 'FAIL':

                        $return['message'] = $result['return_msg'];

                        break;
                }
            }
        }

        return $return;
    }


    /**
     * [微信支付]
     * @param  [type] $order_sn    [description]
     * @param  [type] $pay_price   [description]
     * @param  [type] $create_time [description]
     * @return [type]              [description]
     */
    public function wxpay($order_sn, $pay_price, $subject, $goods_ids)
    {
        $return = ['status'=>1, 'message'=>'', 'data'=>''];

        // $wxpay = app('wxpay');

        $wxpay = new Wxpay(config('latrell-wxpay'));

        $native = $wxpay->native();

        $input = new UnifiedOrder();

        $trade_type = 'NATIVE';

        $input->setOutTradeNo($order_sn);
        $input->setBody($subject);
        $input->setTotalFee(intval($pay_price*10*10));
        // $input->setTotalFee(1);
        $input->SetTrade_type($trade_type);
        $input->setProductId($goods_ids);
        $input->SetNotify_url(config('latrell-wxpay.notify_url'));
        // $input->SetNotify_url('http://117.158.194.99:8080/wxnotify.php');

        $result = $native->GetPayUrl($input);

        if ($result) {
            Log::info('结果：'.json_encode($result));
            $wxpay_url = 'weixin://wap/pay?';

            $wxpay_url .= 'appid%3D'.$result['appid'].'%26';

            $wxpay_url .= 'noncestr%3D'.$result['nonce_str'].'%26';

            $wxpay_url .= 'package%3DWAP%26';

            $wxpay_url .= 'prepayid%3D'.$result['prepay_id'].'%26';

            $wxpay_url .= 'timestamp%3D'.time().'%26';

            $wxpay_url .= 'sign%3D'.$result['sign'];
        }
        /*echo '<BR>res:'.$res;
        echo '<BR>url encode res:'.urlencode($res);
        dd($result);
        return $result;*/

        return $wxpay_url;
    }

    /**
     * [微信支付异步回调]
     * @param  string $order_id [订单id]
     * @return [type]        [description]
     */
    public function wxPayServerBack(Request $request, OrderService $orderService)
    {
        $return = ['status'=>1, 'message'=>'', 'data'=>''];

        Log::info('微信支付异步回调页面');

        $xml = file_get_contents('php://input');

        Log::info('回调结果参数 xml:'.$xml);

        $wxpay = new Wxpay(config('latrell-wxpay'));

        $notify = $wxpay->notify();

        $result = $notify->Handle();

        if ($result && $result['return_code']=='SUCCESS') {

            // $xml = file_get_contents('php://input');

            //如果返回成功则验证签名
            try {

                $resultParam = Results::Init($xml);

                // Log::info('回调结果参数 result：'.json_encode($resultParam));

            } catch (WxpayException $e) {

                $return['status'] = 0;

                $return['message'] = '微信异步回调信息有误';

                return json_encode($return);
            }

            if ($resultParam['out_trade_no']) {

                $orders = Order::where('order_sn', $resultParam['out_trade_no'])->first();

                if ($orders && $orders->order_status==1) {

                    //修改订单状态

                    $order_pay_id = $orderService->orderPayBack(
                        $resultParam['out_trade_no'],
                        'wxpay',
                        $resultParam['transaction_id'],
                        $resultParam['time_end'],
                        json_encode($resultParam)
                    );

                    if ($order_pay_id){

                        return json_encode($return);
                        // return 'success';
                    }

                    Log::debug('Alipay notify get data verification success.', [
                        'out_trade_no' => $resultParam['out_trade_no'],
                        'transaction_id' => $resultParam['transaction_id']
                    ]);
                }
            }
        }else{

            $return['status'] = 0;

            $return['message'] = '微信异步回调信息验证有误';
        }

        return json_encode($return);

    }


    /**
     * [生成二维码]
     * @param string $value [description]
     */
    public function QRcode($code_url, $scan_name = 'wxpay')
    {

        //set it to writable location, a place for temp generated PNG files
        // $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
        // $PNG_TEMP_DIR = public_path().DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
        /*$PNG_TEMP_DIR = DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;

        //html PNG location prefix
        $PNG_WEB_DIR = DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR.$scan_name.'.png';

        //ofcourse we need rights to create temp dir
        if (!file_exists($PNG_TEMP_DIR))
            mkdir($PNG_TEMP_DIR);

        $filename = $PNG_TEMP_DIR.$scan_name.'.png';*/

        //processing form input
        //remember to sanitize user input in real-life solution !!!
        $errorCorrectionLevel = 'L';
        if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], array('L','M','Q','H')))
            $errorCorrectionLevel = $_REQUEST['level'];

        $matrixPointSize = 4;
        if (isset($_REQUEST['size']))
            $matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10);

        if (isset($_REQUEST['data'])) {

            if (trim($_REQUEST['data']) == '')
                die('data cannot be empty! <a href="?">back</a>');

            // user data
            $filename = $PNG_TEMP_DIR.'test'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';

            \PHPQRCode\QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2);
        } else {

            //default data
            // echo 'You can provide data in GET parameter: <a href="?data=like_that">like that</a><hr/>';

            // \PHPQRCode\QRcode::png($code_url, $filename, $errorCorrectionLevel, $matrixPointSize, 2);
            \PHPQRCode\QRcode::png($code_url, false, $errorCorrectionLevel, $matrixPointSize, 2);
            $xmlstr =  @$GLOBALS[HTTP_RAW_POST_DATA];
            // if(empty($xmlstr)) $xmlstr = file_get_contents('php://input');
        }

        // return $PNG_WEB_DIR;
    }


    /**
     * 微信订单查询
     * @param  string $value [description]
     * @return [type]        [description]
     */
    public function wxpayOrderQuery($order_sn, $return_type='array')
    {
        $return = ['status'=>1, 'message'=>'', 'data'=>'', 'xml'=>''];
        Log::info('根据订单号['.$order_sn.']查询在微信的支付结果');

        $user=Auth::user();

        if (empty($user->id)) {

            $return['status'] = 0;

            $return['message'] = '用户id获取失败';

            return $return;
        }

        $order_sn = Order::where('user_id', $user->id)->where('order_sn', $order_sn)->pluck('order_sn');
        // $order_sn = Order::where('user_id', 59)->where('order_sn', $order_sn)->pluck('order_sn');


        if (empty($order_sn)) {

            $return['status'] = 0;

            $return['message'] = '订单id和用户不符';

            return $return;
        }

        $wxpay = new Wxpay(config('latrell-wxpay'));

        $orderQuery = $wxpay->OrderQuery();

        $input = new OrderQuery();

        $input->setOutTradeNo($order_sn);

        $result = $orderQuery->queryOrder($input);

        switch ($result['return_code']) {

            case 'SUCCESS':

                switch ($result['result_code']) {

                    case 'SUCCESS':

                        $return['data'] = $result;

                        //将数组转换为xml格式
                        $xml = simplexml_load_string('<request />');

                        $this->arrayToXmlLeen($return['data'], $xml);

                        $return['xml'] = $xml->saveXML();


                        if ($result['trade_state']!=='SUCCESS') {

                            $return['status'] = 0;

                            switch ($result['trade_state']) {
                                case 'SUCCESS':
                                    $return['status'] = 1;

                                    // $return['message'] = '支付成功';
                                    $return['msg'] = '支付成功';

                                    break;

                                case 'REFUND':

                                    // $return['message'] = '转入退款';
                                    $return['msg'] = '转入退款';

                                    break;


                                case 'NOTPAY':
                                    // $return['status'] = 1;

                                    // $return['message'] = '未支付';
                                    $return['msg'] = '未支付';

                                    break;


                                case 'CLOSED':

                                    // $return['message'] = '已关闭';
                                    $return['msg'] = '已关闭';

                                    break;


                                case 'REVOKED':

                                    // $return['message'] = '已撤销（刷卡支付）';
                                    $return['msg'] = '已撤销（刷卡支付）';

                                    break;


                                case 'USERPAYING':

                                    // $return['message'] = '用户支付中';
                                    $return['msg'] = '用户支付中';

                                    break;


                                case 'PAYERROR':

                                    // $return['message'] = '支付失败(其他原因，如银行返回失败)';
                                    $return['msg'] = '支付失败(其他原因，如银行返回失败)';

                                    break;
                            }

                            return $return;
                        }

                        break;

                    case 'FAIL':

                        $return['status'] = 0;

                        // $return['message'] = '错误码：'.$result['err_code'].'||错误描述：'.$result['err_code_des'];
                        $return['msg'] = '错误码：'.$result['err_code'].'||错误描述：'.$result['err_code_des'];

                        return $return;

                        // return false;

                        break;
                }

                break;

            case 'FAIL':

                $return['status'] = 0;

                // $return['message'] = $result['return_msg'];
                $return['msg'] = $result['return_msg'];

                return $return;


                // return false;

                break;
        }

        if ($return_type=='array') {

            return $return;
        }else{

            return json_encode($return);
        }
    }

    /**
     * [将数组转换为xml格式]
     * @param  [type] $ar  [description]
     * @param  [type] $xml [description]
     * @return [type]      [description]
     */
    public function arrayToXmlLeen($ar, $xml)
    {
        foreach($ar as $k=>$v) {
            if(is_array($v)) {
                $x = $xml->addChild($k);
                $this->arrayToXmlLeen($v, $x);
            }else $xml->addChild($k, $v);
        }
    }

}
